#define AE_USEMEMORYMANAGER
#define AE_OPENGL

#include <AEEngine.h>
#include "Custom2DRenderLoop.h"

Custom2DRenderLoop::Custom2DRenderLoop( void )
{
	m_bInitialized = 0;
	m_lpGeometryInstanceCollection = AENULL;
	InitRenderLoop();
}

Custom2DRenderLoop::~Custom2DRenderLoop( void )
{
	DeInitRenderLoop();
}

void Custom2DRenderLoop::InitRenderLoop( void )
{
	if( m_bInitialized )
		DeInitRenderLoop();

	m_uiFrameCounter = 0;
	m_bInitialized = AETRUE;

	if( m_lpGeometryInstanceCollection == AENULL )
		m_lpGeometryInstanceCollection = new AEStaticGeometryInstanceCollection( 512 );

	AERenderContext *lpContext = AEngine::GetMainRenderContext();

	if( lpContext->GetRenderLoop() != this )
	{
		lpContext->SetClipPlanes( -1.0f, 1.0f );
		lpContext->SetProjectionType( AEProjectionType::AEPROJECTIONTYPE_ORTHOGRAPHIC );
		lpContext->SetRenderLoop( this );
		//lpContext->SetViewport( 0, 0, 320, 240, 1.0, -1.0 );
		AECamera *lpCamera = lpContext->GetCamera();

		AEMatrix4f matLookAt;
		matLookAt.SetLookAtMatrix( AEVector4f( 0.0f, 0.0f, 1.0f, 1.0f ), AEVector4f( 0.0f, 0.0f, 0.0f, 1.0f ), AEVector4f( 0.0f, 1.0f, 0.0f, 1.0f ) );
		lpCamera->Set( matLookAt );
	}
}

void Custom2DRenderLoop::DeInitRenderLoop( void )
{
	if( !m_bInitialized )
		return;
	
	m_bInitialized = AEFALSE;
	m_lpGeometryInstanceCollection->Clear();
}

void Custom2DRenderLoop::_setupMeshBuffer()
{
	AEFLOAT32 vertices[] = { 
        // Pos      // Tex
        0.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 0.0f, 0.0f, 
    
        0.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 1.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 0.0f
    };

	struct MeshVertex
	{
	  AEFLOAT32 fXpos;
	  AEFLOAT32 fYpos;
	  AEFLOAT32 fTex1;
	  AEFLOAT32 fTex2;
	};

	// set up vertex format
	AEVertexDescriptor desc;
	desc.m_sStride = sizeof(MeshVertex);
	desc.m_sPosOfs = offsetof(MeshVertex, fXpos) | AEVERTEXDESC_FORMAT_FLOAT2;
	desc.m_sTexCoordOfs[0] = offsetof(MeshVertex, fTex1) | AEVERTEXDESC_FORMAT_FLOAT2;

	AEMeshBufferPtr spMeshBuffer = new AEMeshBuffer( desc, 6, AEPRIMITIVETYPE_TRILIST, 0, 2, AEMEMUSAGE_STATIC );
	spMeshBuffer->FlagAsLoaded();

	MeshVertex* pVertex = static_cast<MeshVertex*>(spMeshBuffer->LockVertices(AELOCKFLAG_DISCARDABLE));
	memcpy( pVertex, &vertices, sizeof(MeshVertex)*6);
	spMeshBuffer->UnLockVertices();

	AEStaticMeshPtr spStaticMesh = new AEStaticMesh();
	spStaticMesh->AllocateSubmeshes(1);
	spStaticMesh->SetMeshBuffer( spMeshBuffer );

	AEStaticSubmesh *lpSubMesh = spStaticMesh->GetSubmesh(0);
	lpSubMesh->SetRenderVertexRange( 0, 6 );

	AEMatrix4f matModel;
	matModel.SetIdentity();

	AEStaticMeshInstance *lpInst = spStaticMesh->CreateInstance( matModel );

}

void Custom2DRenderLoop::_drawSprite( AEVector4f &vcPos, AEColor crColor, AETexture *lpTex )
{

}

void Custom2DRenderLoop::OnDoRenderLoop( void *lpUserData )
{
	m_uiFrameCounter++;

	AERenderContext *lpContext = AERenderContext::GetCurrentContext();
	//glBindFramebuffer(GL_FRAMEBUFFER, 0);

	//AEMatrix4f matProj = lpContext->GetProjectionMatrix();

	/*GLint programID;
	glGetIntegerv (GL_CURRENT_PROGRAM,&programID );

	GLfloat fMatrix[16];

	matProj.Get( fMatrix, AEMatrixLayout::AEML_RowMajor );
	GLuint MatrixID = glGetUniformLocation( programID, "MatProj" );

	glUniformMatrix4fv( MatrixID, 1, GL_FALSE, (GLfloat *)&fMatrix );*/

	const AEINT32 nRenderFlags = lpContext->GetRenderFlags();
	if( !( nRenderFlags & AERENDERCONTEXTFLAG_NO_CLEARSCREEN ) )
	{
		AEngine::RenderLoopHelper.ClearScreen();
	}

	m_lpGeometryInstanceCollection->Clear();

	AESceneManagerI *lpMgr = AEngine::GetSceneManager();
	AEINT32 nZones = lpMgr->GetNumVisibilityZones();
	
	for( AEINT32 i=0; i<nZones; i++ )
	{
		AEVisibilityZone *lpZone = lpMgr->GetVisibilityZone(i);
		m_lpGeometryInstanceCollection->AppendCollection( *(lpZone->GetStaticGeometryInstances()) );
	}

	AEngine::RenderLoopHelper.RenderStaticGeometryWithShader( *m_lpGeometryInstanceCollection, AECompiledShaderPass() );

	//glBindFramebuffer( GL_FRAMEBUFFER, ((AERenderableTexture *)lpContext->GetRenderTarget())->GetRenderTarget() );
	/*AEINT32 nGeometries = m_lpGeometryInstanceCollection->GetNumEntries();
	for( AEINT32 i=0; i<nGeometries; i++ )
	{
		AEStaticGeometryInstance *lpGeom = m_lpGeometryInstanceCollection->GetEntry( i );
		//lpGeom->
		lpGeom->Render();
	}*/

	SwapBuffers( GetDC( AEngine::GetDefaultVideoConfig()->GetSpecificPlatformInfo()->lpWindow->GetHandle() ) );
}
